import { Alert, Tabs, TabItem } from '@aws-amplify/ui-react';

<Alert
  variation="warning"
  isDismissible={false}
  hasIcon={true}
  heading=""
  >
  You must render the `Authenticator` UI component before using the `useAuthenticator` hook. This hook was designed to retrieve `Authenticator` UI specific state such as `route` and `user` and should not be used without the UI component.
  <br/>
  For a full example of `useAuthenticator`, see the [protected routes guide](../../guides/auth-protected)
</Alert>


## useAuthenticator Hook

`@aws-amplify/ui-react` ships with `useAuthenticator` React hook that can be used to access, modify, and update Authenticator's auth state. To use them, you must render the Authenticator and wrap your application with [`<Authenticator.Provider>`](#authenticator-provider):

```tsx
import { Authenticator } from '@aws-amplify/ui-react';

export default () => (
  <Authenticator.Provider>
    <App />
  </Authenticator.Provider>
);
```

Then, you can use `useAuthenticator` on your App:

```tsx
import { useAuthenticator } from '@aws-amplify/ui-react';

const App = () => {
  const { user, signOut } = useAuthenticator((context) => [context.user]);
  // ...
};
```

## Authenticator Provider

In advanced use cases where usage of the [`useAuthenticator` hook](advanced#useauthenticator-hook) outside the scope of the [`Authenticator`](../authenticator) is needed, wrap your application inside an `Authenticator.Provider`. The `Authenticator.Provider` guarantees that the [useAuthenticator hook](advanced#useauthenticator-hook) is available throughout your application. You can see an example of this pattern in the [Protected Routes Guide.](../../guides/auth-protected)

<Tabs>
<TabItem title="Create React App">
```jsx
import { Authenticator, View } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css'; // default theme

export default function App() {
  return (
    <Authenticator.Provider>
      <View>Your app here</View>
    </Authenticator.Provider>
  );
};
```
</TabItem>
<TabItem title="Next.js" >
```jsx
import { Authenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css'; // default theme

export default function App(props) {
  return (
    <Authenticator.Provider>
      <View {...props}>Your app here</View>
    </Authenticator.Provider>
  );
};
```
</TabItem>
</Tabs>

## Prevent Re-renders

Using `useAuthenticator` hook at your `App` level is risky, because it'll trigger a re-render down its tree whenever any of its context changes value.

To prevent undesired re-renders, you can pass a function to `useAuthenticator` that takes in Authenticator context and returns an array of desired context values. The hook will only trigger re-render if any of the array values change.

For example, you can ensure `useAuthenticator` to only reevaluate when its `user` context changes:

```tsx
import { useAuthenticator } from '@aws-amplify/ui-react';

// hook below is only reevaluated when `user` changes
const { user, signOut } = useAuthenticator((context) => [context.user]);
```
